package com.a9_lin.www.testormlite;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.a9_lin.www.testormlite.bean.UserInfoListBean;
import com.a9_lin.www.testormlite.bean.Userinfo;
import com.a9_lin.www.testormlite.bean.Watch;
import com.a9_lin.www.testormlite.dao.NewUserInfoListDao;
import com.a9_lin.www.testormlite.dao.UserInfoDao;
import com.a9_lin.www.testormlite.dao.UserInfoListDao;
import com.a9_lin.www.testormlite.dao.WatchDao;

import java.util.ArrayList;

import static android.util.Log.d;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private Context mContext;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = this;

//        testA();
//
//        testB();
//
//        testC();

        testD();

    }

    //将插入的逻辑之类的东西放到Dao类中 这里无需关心 在数据库中存储任何类 只需调用对应类的insert方法即可
    private void testD(){
        //以下的逻辑模拟我们正常情况下从服务器映射回来的数据 没有任何与数据库相关的内容
        UserInfoListBean userInfoListBean = new UserInfoListBean();
        ArrayList<Userinfo> userinfos = new ArrayList<>();
        for(int i = 0;i<3;i++){
            Watch watch = new Watch();
            watch.setIMEI(i+"");
            Userinfo userinfo = new Userinfo();
            userinfo.setWatch(watch);
            userinfos.add(userinfo);
        }

        userInfoListBean.setUserinfos(userinfos);

        //这里我们只需调用最外层类的insert方法 具体的业务逻辑交给具体的Dao类去处理

        NewUserInfoListDao.getInstance(mContext).insert(userInfoListBean);

//        new NewUserInfoListDao(mContext).insert(userInfoListBean);

        //查询数据库 一切数据格式正常
        d(TAG,"查询数据库："+new UserInfoListDao(mContext).queryAllWithWatch().toString());
    }

    //测试外键属性为集合的类型插入到数据库中
    private void testC(){

        //该类型中字段中含有一个集合类 由于ormlite的外键集合只支持ForeignCollection或者Collection 所以这里选了Collection类 因为还需要支持某些实体类映射框架
        //具体内容参见实体类内部注释
        /**
         * @see UserInfoListBean
         */
        UserInfoListBean userInfoListBean = new UserInfoListBean();

        //当含有集合类的外键的时候 需要先将外部类A插入到表中 因为只有当外部类A插入到数据库中后 对应的字段下才会有数据 此时给字段中的实体类B设置对应属性的时候
        //他才会根据这个数据 找到他是属于哪一个外部类A的 这样我们从数据库中取回的数据才是正确的
        new UserInfoListDao(mContext).insert(userInfoListBean);

        ArrayList<Userinfo> userinfos = new ArrayList<>();
        for(int i = 0;i<3;i++){
            Watch watch = new Watch();
            watch.setIMEI(i+"");
            new WatchDao(mContext).insert(watch);
            Userinfo userinfo = new Userinfo();
            userinfo.setWatch(watch);
            /**
             * 与我们正常的实体类写法不同的就是我们这里需要给内部类B设置外部类A的引用
             * @see Userinfo 这样的不同也就造成了 我们从服务器取回的数据 直接映射成实体类的那些数据是不能直接使用的 需要做一定的处理才可以
             */
            userinfo.setUserInfoListBean(userInfoListBean);
            new UserInfoDao(mContext).insert(userinfo);
            userinfos.add(userinfo);
        }

        //经过以上步骤以后 不需要将B设置给A 即可从数据库中正确的查到数据

        d(TAG,userInfoListBean.toString());
        d(TAG,userinfos.toString());

        //查询数据库 一切数据格式正常
        d(TAG,"查询数据库："+new UserInfoListDao(mContext).queryAllWithWatch().toString());

    }

    //测试普通类插入数据库
    private void testA(){
        Watch watch = new Watch();

        watch.setIMEI("123456");

        new WatchDao(mContext).insert(watch);

        d(TAG,"数据库查询结果"+new WatchDao(mContext).queryAll().toString());
        d(TAG,"数据库删除结果"+new WatchDao(mContext).delete(watch));
        d(TAG,"数据库再次查询结果"+new WatchDao(mContext).queryAll().toString());
    }

    //测试实体类A中有另外的实体类B 也就是表中关联外键的情况
    private void testB(){

        Watch watch = new Watch();

        watch.setIMEI("123456");

        //需要先将外键B类插入到表中 单独只插入A是不行的
        new WatchDao(mContext).insert(watch);

        Userinfo userinfo = new Userinfo();

        //给A类型设置属性B类 此时A类和B类关联成功
        userinfo.setWatch(watch);

        //存储A类 此时A类中B类对应的字段下 存储着B类中的主键id 以供以后的增删改查操作时查询到对应的B类对象
        new UserInfoDao(mContext).insert(userinfo);

        //此时查询数据正常
        d(TAG,"userinfo插入之后，查询watch表所得结果"+new WatchDao(mContext).queryAll().toString());

        d(TAG,"数据库查询结果"+new UserInfoDao(mContext).queryAllWithWatch().toString());

        //修改B类中的某个属性
        watch.setIMEI("123456789");

        //更新B类
        new WatchDao(mContext).update(watch);

        //然后此时查询数据库 由于关联的主键没有变化 所以此时数据正常
        d(TAG,"watch表修改之后查询所得结果"+new WatchDao(mContext).queryAll().toString());

        d(TAG,"数据库查询结果"+new UserInfoDao(mContext).queryAllWithWatch().toString());

        //不需要重新给A类设置B类对象 也不需要重新更新对象 所以这两步是多余的
        userinfo.setWatch(watch);

        new UserInfoDao(mContext).update(userinfo);

        d(TAG,"userinfo更新之后查询结果"+new UserInfoDao(mContext).queryAllWithWatch().toString());


        //这里再次修改 不仅修改属性 还修改了主键 然后重复上边的查询
        watch.setIMEI("123");
        watch.setId(10);

        //此时更新数据 由于数据库中没有改id的数据 所以真实数据并没有修改
        new WatchDao(mContext).update(watch);

        //此时的查询结果是没有修改之前的结果 也就是说这次的修改是无效的
        d(TAG,"watch表修改之后查询所得结果"+new WatchDao(mContext).queryAll().toString());

        d(TAG,"数据库查询结果"+new UserInfoDao(mContext).queryAllWithWatch().toString());

        //这个时候重新给A类设置B类
        userinfo.setWatch(watch);

        //然后更新数据 此时就出现问题了 由于更新了A类 B类中的主键id属性发生了变化 A类中B类对应的外键下的关联属性也就跟着变成了10
        new UserInfoDao(mContext).update(userinfo);

        //此时再查询数据 A类根据外键的属性去B类的表中查询主键id为10的数据 然而并没有 所以此时返回的就是空 B类的数据查询不到了
        d(TAG,"userinfo更新之后查询结果"+new UserInfoDao(mContext).queryAllWithWatch().toString());

        //此时删除A类数据
        d(TAG,"数据库删除结果"+new UserInfoDao(mContext).delete(userinfo));
        //再次查询 A类为空了
        d(TAG,"数据库再次查询结果"+new UserInfoDao(mContext).queryAll().toString());

        //但再次查询B类 发现B类还是有数据 所以B类需要单独去删除
        d(TAG,"数据库删除userinfo之后，查询watch表所得结果"+new WatchDao(mContext).queryAll().toString());

        //总结下：类与类相互嵌套的时候 两个类都需要单独的进行增删改查 增删改查之后 只需要独立做更新就可以了 不需要重新进行设置更新 只需要在查询的时候刷新一下即可
        // 除非是主键变化 也就是说两个类相关联的地方发生变化
    }
}
